﻿Imports Clo = Enhancements.Core.Logging
Imports Ere = Enhancements.Basic.RegularExpressions
Imports Exe = Enhancements.Basic.Expressions
Imports Gen = System.Collections.Generic
Imports Glo = System.Globalization
Imports Iou = System.IO
Imports Ope = Enhancements.Basic.Expressions.Operators
Imports Ref = System.Reflection
Imports Reg = System.Text.RegularExpressions
Imports Sys = System
Imports Tex = System.Text
Imports Val = Enhancements.Basic.Expressions.Values
Imports Xsd = System.Xml.Schema
Imports W3c = System.Xml

Namespace Enhancements.Basic.Expressions.Functions
    ''' <summary>It is the functions base class. For a function to be created, it must derive from Function.</summary>
    <Serializable(), DebuggerStepThrough()> _
    Public MustInherit Class [Function]

        ''' <summary>Initializes a Function instance with the specified name and signatures, and an optional operator.</summary>
        ''' <param name="_name">Name specification.</param>
        ''' <param name="_signatures">Signatures specification.</param>
        ''' <param name="_operator">Operator specification. It is optional.</param>
        ''' <exception cref="FunctionNameIsValidNotException">_name is invalid.</exception>
        ''' <exception cref="FunctionSignaturesAreValidNotException">_signatures is invalid.</exception>
        ''' <exception cref="FunctionOperatorIsValidNotException">_operator is invalid.</exception>
        Protected Sub New(ByVal _name As System.String, ByVal _signatures() As FunctionSignature, ByVal _operator As FunctionOperator)
            Name = _name
            Signatures = _signatures
            [Operator] = _operator
        End Sub

        Private __Name As System.String = Nothing
        ''' <summary>Gets the name specified.</summary>
        Public Property Name() As System.String
            Get
                Return __Name
            End Get
            Private Set(ByVal _value As System.String)
                Try
                    ___Identifiers.AssertIsValid(_value, True)
                    Dim _valueIncompatibilityList As Gen.List(Of System.String) = New Gen.List(Of System.String)()
                    _valueIncompatibilityList.Add(_value)
                    _valueIncompatibilityList.Add(Val.Boolean.TrueValueRepresentation)
                    _valueIncompatibilityList.Add(Val.Boolean.FalseValueRepresentation)
                    _valueIncompatibilityList.AddRange(Ope.Operator.___OperatorsSortedGet().Keys.ToArray())
                    ___Identifiers.AssertAreRepeatedNot(_valueIncompatibilityList.ToArray(), True)
                Catch _exception As Exception
                    FunctionNameIsValidNotException.___Throw(_value, _exception)
                End Try

                __Name = _value
            End Set
        End Property

        Private __Signatures() As FunctionSignature = {}
        ''' <summary>Gets the signatures specified.</summary>
        Public Property Signatures() As FunctionSignature()
            Get
                Return __Signatures
            End Get
            Private Set(ByVal _value() As FunctionSignature)
                Try
                    _value.IsListFilled("_value", True)
                    _value.Length.IsInRange("Signatures._value.Length", 1, Sys.Int32.MaxValue, True)
                    For _counter1 As Sys.Int32 = 0 To _value.Length - 1
                        For _counter2 As Sys.Int32 = _counter1 + 1 To _value.Length - 1
                            _value(_counter1).Equals(_value(_counter2)).IsTrueNot("_value(_counter1).Equals(_value(_counter2))", True)
                        Next _counter2
                    Next _counter1
                Catch _exception As Exception
                    FunctionSignaturesAreValidNotException.___Throw(_value, _exception)
                End Try

                __Signatures = _value
            End Set
        End Property

        Private __Operator As FunctionOperator = Nothing
        ''' <summary>Gets the operator specified. When specified, it allows a function call to be specified by using operator-like syntax.</summary>
        Public Property [Operator]() As FunctionOperator
            Get
                Return __Operator
            End Get
            Private Set(ByVal _value As FunctionOperator)
                Try
                    If _value.IsNullNot("Operator._value", False) Then
                        For Each _signature As FunctionSignature In Signatures
                            _signature.Parameters.Length.IsInRange("_signature.Parameters.Length", 1, 2, True)
                        Next _signature
                    End If
                Catch _exception As Exception
                    FunctionOperatorIsValidNotException.___Throw(_value, _exception)
                End Try

                __Operator = _value
            End Set
        End Property

        ''' <summary>Solves a function call by using the supplied signature and parameters values.</summary>
        ''' <param name="_signature">Signature specified.</param>
        ''' <param name="_parametersValues">Parameters values specified. If none, an empty array is passed.</param>
        ''' <remarks>The execution of this function implementations are considered to deliver correct results only when called through the expressions subsystem. If called directly by user code, the returned results may be incorrect.</remarks>
        ''' <exception cref="Sys.Exception">Any exception can be throwed by an implementation of this function as a result of the impossibility of generating a correct end result.</exception>
        ''' <returns> </returns>
        Public MustOverride Function Solve(ByVal _signature As FunctionSignature, ByVal _parametersValues() As Sys.Object) As Sys.Object

    End Class
End Namespace
